package com.zp.qualitypractice;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.content.LocalBroadcastManager;

import com.elvishew.xlog.LogConfiguration;
import com.elvishew.xlog.LogLevel;
import com.elvishew.xlog.XLog;
import com.elvishew.xlog.flattener.ClassicFlattener;
import com.elvishew.xlog.interceptor.BlacklistTagsFilterInterceptor;
import com.elvishew.xlog.printer.AndroidPrinter;
import com.elvishew.xlog.printer.ConsolePrinter;
import com.elvishew.xlog.printer.Printer;
import com.elvishew.xlog.printer.file.FilePrinter;
import com.elvishew.xlog.printer.file.backup.NeverBackupStrategy;
import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator;
import com.github.moduth.blockcanary.BlockCanary;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
import com.zp.qualitypractice.Utils.OsUtils;
import com.zp.qualitypractice.Utils.PhoneStatusUtils;
import com.zp.qualitypractice.io.InitIntentService;
import com.zp.qualitypractice.io.RetrofitHelper;
import com.zp.qualitypractice.rx.RxBus;

import java.io.File;

import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by izp on 2017/4/6.
 */

public class App extends Application {
    private static App mInstance;
    private int appCount = 0;
    private RefWatcher refWatcher;

    private ActivityStack activitysQueue = ActivityStack.getInstance();
    private ActivityWeakStack activityWeakStack = ActivityWeakStack.getManager();
    private ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) {
            ALog.v("activity监听"+activity.getClass().getSimpleName());
            activitysQueue.addActivity(activity);//创建
            activityWeakStack.addActivity(activity);
        }
        @Override
        public void onActivityDestroyed(Activity activity) {
            ALog.v("activity监听"+activity.getClass().getSimpleName());
            activitysQueue.popCurrentActivity();// 推出
            activityWeakStack.popCurrentActivity();
        }

        @Override
        public void onActivityStarted(Activity activity) {
            appCount++;
            ALog.v("activity监听"+activity.getClass().getSimpleName());
            ALog.v("local","后台监听");
        }

        @Override
        public void onActivityResumed(Activity activity) {
            ALog.v("activity监听"+activity.getClass().getSimpleName());
        }

        @Override
        public void onActivityPaused(Activity activity) {
            ALog.v("activity监听"+activity.getClass().getSimpleName());
        }

        @Override
        public void onActivityStopped(Activity activity) {
            appCount--;
            ALog.v("activity监听"+activity.getClass().getSimpleName());
            XLog.st(0).tag("local").d("后台监听");
            float rateOfUsed = 1.0f * Runtime.getRuntime().totalMemory() / Runtime.getRuntime().maxMemory();

            //内存不足时，清空缓存
            if (rateOfUsed > 0.6) {
//                SHAnalyticManager.onEvent("out_of_memory");
//                CacheUtil.clear();
            }

            //退到后台后，清除缓存
//            if (0 >= activityList.size()) {

//                CacheUtil.clear();

//                RxBus.getDefault().post(new BackgroundEvent(true));

//            }
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
            ALog.v("activity监听"+activity.getClass().getSimpleName());
        }
    };
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        String processName = OsUtils.getProcessName(this, android.os.Process.myPid());
        if (processName != null) {
            boolean defaultProcess = processName.equals(App.getApp().getPackageName());
            // 默认的主进程启动时初始化应用
            if (defaultProcess) {
                initAppForMainProcess();
            } else if (processName.contains(":redress")) {
                // 其他进程启动时初始化对应内容
            }
        }
    }

    private void initAppForMainProcess() {
        initLeakCanary();
        initBlockCanary();
        initLog();
        registerActivityLifecycleCallbacks(activityLifecycleCallbacks);
        InitIntentService.start(this);//通过intentService进行App异步初始化。
//        最后不要忘记在Mainifest注册Service。
//        RxBus.getDefault().toObservable(String.class).observeOn(Schedulers.io()).subscribe(new Consumer<String>() {
//            @Override
//            public void accept(@NonNull String s) throws Exception {
//
//            }
//        });
    }

    public static App getApp(){
        return mInstance;
    }
    public static Context getAppContext(){
        return mInstance.getApplicationContext();
    }
    private void initBlockCanary(){
        BlockCanary.install(this, new AppBlockCanaryContext());
    }
    public static RefWatcher getRefWatcher(Context context) {
        App application = (App) context.getApplicationContext();
        return application.refWatcher;
    }
    private RefWatcher initLeakCanary() {
        /*
        LeakCanary.install() 会返回一个预定义的 RefWatcher，同时也会启用一个 ActivityRefWatcher，
        用于自动监控调用 Activity.onDestroy() 之后泄露的 activity。
        而观察Fragment需要代码中埋入
        * */
        if (BuildConfig.DEBUG){
            refWatcher = LeakCanary.install(this);
        }else {
            refWatcher = RefWatcher.DISABLED;
        }
        return refWatcher;
    }
    private void initLog(){
        initALog();
        initXLog();
    }
    // init it in ur application
    public void initALog() {
        ALog.Config config = ALog.init(this)
                .setLogSwitch(BuildConfig.DEBUG)// 设置log总开关，包括输出到控制台和文件，默认开
                .setConsoleSwitch(BuildConfig.DEBUG)// 设置是否输出到控制台开关，默认开
                .setGlobalTag("vicky")// 设置log全局标签，默认为空
                // 当全局标签不为空时，我们输出的log全部为该tag，
                // 为空时，如果传入的tag为空那就显示类名，否则显示tag
                .setLogHeadSwitch(true)// 设置log头信息开关，默认为开
                .setLog2FileSwitch(false)// 打印log时是否存到文件的开关，默认关
                .setDir("")// 当自定义路径为空时，写入应用的/cache/log/目录中
                .setBorderSwitch(false)// 输出日志是否带边框开关，默认开
                .setConsoleFilter(ALog.V)// log的控制台过滤器，和logcat过滤器同理，默认Verbose
                .setFileFilter(ALog.V);// log文件过滤器，和logcat过滤器同理，默认Verbose
        ALog.d(config.toString());
    }
    public void initXLog(){
        LogConfiguration config = new LogConfiguration.Builder()
                .logLevel(BuildConfig.DEBUG ? LogLevel.ALL             // 指定日志级别，低于该级别的日志将不会被打印，默认为 LogLevel.ALL
                        : LogLevel.NONE)
                .tag("vicky")                                         // 指定 TAG，默认为 "X-LOG"
                .t()                                                   // 允许打印线程信息，默认禁止
                .st(0)                                                 // 允许打印深度为2的调用栈信息，默认禁止
//                .b()                                                   // 允许打印日志边框，默认禁止
//                .jsonFormatter(new MyJsonFormatter())                  // 指定 JSON 格式化器，默认为 DefaultJsonFormatter
//                .xmlFormatter(new MyXmlFormatter())                    // 指定 XML 格式化器，默认为 DefaultXmlFormatter
//                .throwableFormatter(new MyThrowableFormatter())        // 指定可抛出异常格式化器，默认为 DefaultThrowableFormatter
//                .threadFormatter(new MyThreadFormatter())              // 指定线程信息格式化器，默认为 DefaultThreadFormatter
//                .stackTraceFormatter(new MyStackTraceFormatter())      // 指定调用栈信息格式化器，默认为 DefaultStackTraceFormatter
//                .borderFormatter(new MyBoardFormatter())               // 指定边框格式化器，默认为 DefaultBorderFormatter
//                .addObjectFormatter(AnyClass.class,                    // 为指定类添加格式化器
//                        new AnyClassObjectFormatter())                     // 默认使用 Object.toString()
//                .addInterceptor(new BlacklistTagsFilterInterceptor(    // 添加黑名单 TAG 过滤器
//                        "blacklist1", "blacklist2", "blacklist3"))
                // .addInterceptor(new WhitelistTagsFilterInterceptor( // 添加白名单 TAG 过滤器
                //     "whitelist1", "whitelist2", "whitelist3"))
//                .addInterceptor(new MyInterceptor())                   // 添加一个日志拦截器
                .build();

        Printer androidPrinter = new AndroidPrinter();             // 通过 android.util.Log 打印日志的打印器
//        Printer consolePrinter = new ConsolePrinter();             // 通过 System.out 打印日志到控制台的打印器
//        Printer filePrinter = new FilePrinter                      // 打印日志到文件的打印器
//                .Builder(new File(Environment.getExternalStorageDirectory(), "xlog").getPath())// 指定保存日志文件的路径
//                .fileNameGenerator(new DateFileNameGenerator())        // 指定日志文件名生成器，默认为 ChangelessFileNameGenerator("log")
//                .backupStrategy(new NeverBackupStrategy())              // 指定日志文件备份策略，默认为 FileSizeBackupStrategy(1024 * 1024)
//                        .logFlattener(new ClassicFlattener())                      // 指定日志平铺器，默认为 DefaultFlattener
//                        .build();

        XLog.init(                                                 // 初始化 XLog
                config,                                                // 指定日志配置，如果不指定，会默认使用 new LogConfiguration.Builder().build()
                androidPrinter                                        // 添加任意多的打印器。如果没有添加任何打印器，会默认使用 AndroidPrinter(Android)/ConsolePrinter(java)
//                consolePrinter,
//                filePrinter
        );
    }

    public static RetrofitHelper getDataCenter(){
        return RetrofitHelper.getInstance();
    }

    public LocalBroadcastManager getBroadcast(){
        return  LocalBroadcastManager.getInstance(this);
    }
    public ActivityWeakStack getAppManager(){
        return ActivityWeakStack.getManager();
    }
    public int getAppCount() {
        return appCount;
    }

    public void setAppCount(int appCount) {
        this.appCount = appCount;
    }
}
